package com.wtwd.campus.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.wtwd.campus.common.Constants;
import com.wtwd.campus.common.RespCode;
import com.wtwd.campus.common.RespEntity;
import com.wtwd.campus.dao.*;
import com.wtwd.campus.entity.*;
import com.wtwd.campus.model.vo.ResultVO;
import com.wtwd.campus.service.*;
import com.wtwd.campus.utils.CommandSendUtils;
import com.wtwd.campus.wx.entity.BindingStudentDto;
import com.wtwd.campus.wx.entity.ClassesDto;
import com.wtwd.campus.wx.entity.GradeDto;
import com.wtwd.campus.wx.entity.SchoolDto;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @Author ldaoliang
 * @Date create in 13:58 2021/7/14
 * @Description
 */
@Service
public class WxServiceImpl implements WxService {

    private static final Logger logger = LoggerFactory.getLogger(WxServiceImpl.class);

    @Resource
    private WxMapper wxMapper;
    @Resource
    private DeviceInfoMapper deviceInfoMapper;
    @Resource
    private StudentMapper studentMapper;
    @Resource
    private WXUserStudentPermissionMapper wxUserStudentPermissionMapper;
    @Resource
    private RedisService redisService;
    @Autowired
    private CommandSendUtils commandSendUtils;
    @Resource
    private SysOrgService sysOrgService;
    @Resource
    private SchoolMapper schoolMapper;
    @Resource
    private GradeService gradeService;
    @Resource
    private ClassesService classesService;

    @Autowired
    private IRMFeignClientNettyService irmFeignClientNettyService;

    @Override
    public int[] addOpenIdIfAbsent(String openId) {
        int needBindPhone = 0;
        int wxUserId = 0;
        logger.info("微信用户点击菜单： openId = [{}]", openId);
        WxUser wxUser = wxMapper.getWxUserByOpenId(openId);
        if (wxUser == null) {
            logger.info("微信用户不存在，需要新增且需要绑定号码");
            needBindPhone = 1;
            wxUser = new WxUser();
            wxUser.setOpenId(openId);
            wxUser.setCreateTime(System.currentTimeMillis());
            wxUser.setLastLoginTime(System.currentTimeMillis());
            wxMapper.addWxUser(wxUser);
            wxUserId = wxUser.getWxUserId();
        } else {
            if (StringUtils.isBlank(wxUser.getWxUserPhone())) {
                logger.info("微信用户存在，但是号码为空，需要绑定");
                needBindPhone = 1;
            }
            wxUserId = wxUser.getWxUserId();
            logger.info("微信用户Id ： " + wxUserId);
            wxMapper.updateWxUserLastLoginTime(wxUserId, System.currentTimeMillis());
        }
        return new int[]{needBindPhone, wxUserId};
    }

    @Override
    public WxUser getWxUserByPhone(String phone, Integer customerId) {
        return wxMapper.getWxUserByPhone(phone, customerId);
    }

    @Override
    public WxUser getWxUserById(Integer userId) {
        return wxMapper.getWxUserById(userId);
    }

    @Override
    public int[] bindPhone(WxUser oldWxUser, String phone, String token, Integer customerId) {
        WxUser wxUser = wxMapper.getWxUserByPhone(phone, customerId);
        int[] result = new int[2];
        if (wxUser == null) {
            int i = wxMapper.bindingPhone(oldWxUser.getWxUserId(), phone);
            result[0] = i;
            result[1] = oldWxUser.getWxUserId();
        } else {
            // 删除新生成的openId的user，并且phone对应的userId的openId更新为现在的openId,更新redis缓存的用户id
            String openId = oldWxUser.getOpenId();
            wxMapper.delWxUser(oldWxUser.getWxUserId());
            redisService.setKey(token, String.valueOf(wxUser.getWxUserId()), Constants.WXTOKEN_EXPIRE, TimeUnit.DAYS);
            int i = wxMapper.updateOpenId(openId, wxUser.getWxUserId());
            result[0] = i;
            result[1] = wxUser.getWxUserId();
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> getUserStudentList(Integer UserId) {
        return wxMapper.getUserStudentList(UserId);
    }

    @Override
    public RespEntity bindingStudent(Integer userId, String imei, String name, String studetnNo) {
        // 1. 校验三个参数
        DeviceInfo deviceInfo = deviceInfoMapper.getDeviceInfoByImei(imei);
        if (deviceInfo == null) {
            return new RespEntity(RespCode.DEVICE_NOT_FOUND);
        }
        if (deviceInfo.getDeviceType() != Constants.PLATFORM_DEVICE) {
            return new RespEntity(RespCode.NOT_PLATFORM_DEVICE_CANNOT_BIND);
        }
        Integer studentId = deviceInfo.getStudentId();
        if (studentId == null) {
            return new RespEntity(RespCode.STUDENT_MSG_ERROR);
        }
        Student student = studentMapper.getStudentInfoById(studentId);
        if (student == null) {
            return new RespEntity(RespCode.STUDENT_MSG_ERROR);
        }
        // 名字学号都一样，才进行修改
        if (studetnNo.equals(student.getStudentNo()) && name.equals(student.getStudentName())) {
            // 防止重复绑定
            WxUserStudentPermission wxUserStudentPermission = wxUserStudentPermissionMapper.getWxUserStudentPermissionByCondition(studentId, userId);
            if (wxUserStudentPermission == null) {
                //获取学生的绑定列表
                List<Map<String, Object>> list = wxMapper.bindStudentPhoneList(studentId);
                Integer isMan = 0;
                Integer isAuthority = 0;
                if (list == null || list.size() == 0) {
                    //将该用户设置为管理员并处于授权状态
                    isMan = 1;
                    isAuthority = 1;
                }
                //获取微信用户的手机号码
                WxUser wxUser = wxMapper.getWxUserById(userId);
                wxUserStudentPermissionMapper.addWxUserStudentPermission(wxUser.getWxUserPhone(), studentId, userId, isMan, isAuthority);
                // 更新学生表绑定微信的状态
                studentMapper.updateStudentWxUserBindStatus(1, studentId);
            }
            //如若是喜马拉雅的设备则下发绑定关系指令
            if (!StringUtils.isBlank(deviceInfo.getOrgCode()) && deviceInfo.getOrgCode().contains("A01A03A05")) {
                //设备在线则进行发送
                //根据学生id获取年级、班级、学生名称、学校名称
                Map<String, Object> bindingMap = studentMapper.getStuBindingMessByStuId(deviceInfo.getStudentId());
                bindingMap.put("imei", imei);
                bindingMap.put("status", Constants.DEVICE_BINDING);
                bindingMap.put("commandNumber", getCurTime());
                String s = JSONObject.toJSONString(bindingMap);
                boolean isOnline = deviceOnline(imei);
                //进行指令下发
                commandSendUtils.sendBindingStatus(JSONObject.parseObject(s), Constants.WX_COMMAND_USER_ID, isOnline, false);
            }
            return new RespEntity(RespCode.SUCCESS);
        }
        return new RespEntity(RespCode.STUDENT_MSG_ERROR);
    }


    @Override
    public int unbindStudent(Integer userId, Integer studentId) {
        return wxUserStudentPermissionMapper.delWxUserStudentPermission(studentId, userId);
    }

    @Override
    public List<Map<String, Object>> getStudentList(Integer userId) {
        List<Map<String, Object>> studentList = wxMapper.studentList(userId);
        Long time = System.currentTimeMillis();
        studentList.forEach(map -> {
            if (map.containsKey("imei")) {
               /* if (time - (long) map.get("last_up_time") > Constants.OFF_LINE_TIME) {
                    map.put("status", Constants.WX_DEVICE_OFFLINE);
                } else {
                    map.put("status", Constants.WX_DEVICE_ONLINE);
                }*/
                boolean flag = deviceOnline((String) map.get("imei"));
                if (flag) {
                    map.put("status", Constants.WX_DEVICE_ONLINE);
                } else {
                    map.put("status", Constants.WX_DEVICE_OFFLINE);
                }
            } else {
                map.put("status", Constants.WX_DEVICE_NOT_FOUND);
            }
        });
        return studentList;
    }

    @Override
    public int clearBind(Integer wxUserId) {
        return wxMapper.clearBind(wxUserId);
    }

    @Override
    public List<Map<String, Object>> bindStudentPhoneList(Integer studentId) {
        return wxMapper.bindStudentPhoneList(studentId);

    }

    @Override
    public Integer changeManger(Integer stuId, Integer userId, Integer transferUserId) {
        //将之前的用户设置为非管理员
        Integer i = wxMapper.changeManager(userId, 0, stuId, 1);
        //将现在用户设置为管理员
        Integer i1 = wxMapper.changeManager(transferUserId, 1, stuId, 1);
        return i + i1;
    }

    @Override
    public Map<String, Object> getBindingById(Integer id) {
        return wxMapper.getBindingById(id);
    }

    @Override
    public Integer changeAuthority(Integer id, Integer status) {
        return wxMapper.giveAuthority(id, status);
    }

    @Override
    public Map<String, Object> getBindingByStuIdAndUserId(Integer stuId, Integer userId) {
        return wxMapper.getBindingByStuIdAndUserId(stuId, userId);
    }

    @Override
    public Integer modifyBindingPhoneByUserId(Integer userId, String phone) {
        return wxMapper.modifyBindingPhoneByUserId(userId, phone);
    }

    @Override
    public List<String> getOpenIdListBySchoolId(Integer schoolId) {
        List<Integer> classIdList = wxMapper.getClassIdListBySchoolId(schoolId);
        List<String> openIdList = wxMapper.getOpenIdListByClassIdList(classIdList);
        return openIdList;
    }

    @Override
    public String getClassesMessByUserId(Integer userId) {
        return wxMapper.getClassesMessByUserId(userId);
    }

    @Override
    public List<Map<String, Object>> getClassNameByClassIdList(List<Integer> idList) {
        return wxMapper.getClassNameByClassIdList(idList);
    }

    @Override
    public String getTeacherNameByUserId(Integer userId) {
        return wxMapper.getTeacherNameByUserId(userId);
    }

    @Override
    public List<String> getOpenIdListByClassId(Integer classId) {
        return wxMapper.getOpenIdListByClassId(classId);
    }

    @Override
    public List<Map<String, Object>> getOpenIdAndStuNameListByClassId(Integer classId) {
        return wxMapper.getOpenIdAndStuNameListByClassId(classId);
    }

    @Override
    public WxUser getWxUserByOpenId(String openId) {
        return wxMapper.getWxUserByOpenId(openId);
    }

    @Override
    public List<Map<String, Object>> getOpenIdByStuId(Integer stuId) {
        return wxMapper.getOpenIdByStuId(stuId);
    }

    @Override
    public Integer getWxUserIdByOpenId(String openId) {
        return wxMapper.getWxUserIdByOpenId(openId);
    }

    @Override
    public List<Map<String, Object>> getXMLYStudentList(Integer wxUserId) {
        return wxMapper.xmlyStudentList(wxUserId);
    }

    @Override
    public int modifyPhoneByImei(String imei, String phone) {
        return wxMapper.modifyPhoneByImei(imei, phone);
    }

    @Override
    public int modifyPhoneByDeviceId(Integer deviceId, String phone) {
        return 0;
    }

    @Override
    public Integer updateWxUserCustomerIdByWxUserId(Integer wxUserId, Integer customerId) {
        return wxMapper.updateWxUserCustomerIdByWxUserId(wxUserId, customerId);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean dealOpenStateBasicInformation(WxCustomer wxCustomer, BindingStudentDto data) {
        //该鉴别在本处可以去掉，由于学类信息由服务器默认填充,故不应会出现学校类信息对不上的问题(但考虑到可能会对学生数据进行服务器默认处理,故先保存)
        Boolean rest = authSchoolKind(wxCustomer, data);
        if (!rest) {
            return rest;
        }
        try {
            School school = createSchoolOneName(wxCustomer, data.getSchoolDto());
            Grade grade = new Grade();
            grade.setGradeName(data.getGradeDto().getGradeNames());
            grade.setSchoolId(school.getId());
            grade = createGradeOneName(grade);
            Classes classes = new Classes();
            classes.setClassesName(data.getClassesDto().getClassesName());
            classes.setGradeId(grade.getGradeId());
            classes = createClassesOneName(classes);
            Student student = new Student();
            student.setClassesId(classes.getClassesId());
            student.setStudentName(data.getName());
            student.setStudentNo(data.getStuNo());
            createStudentOneStuNo(school.getId(), student);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    @Override
    public Boolean authSchoolKind(WxCustomer wxCustomer, BindingStudentDto data) {
        StudentSchoolData studentSchoolData = studentMapper.getStudentInfoByCustomerCodeAndStundetNameAndStudentNo(wxCustomer.getCustomerCode(), data.getName(), data.getStuNo());
        if (studentSchoolData == null) {
            return true;
        }
        if (studentSchoolData.getSchoolName().equals(data.getSchoolDto().getSchoolName())
                && studentSchoolData.getGradeName().equals(data.getGradeDto().getGradeNames())
                && studentSchoolData.getClassesName().equals(data.getClassesDto().getClassesName())
        ) {
            return true;
        }
        return false;
    }

    @Override
    public School createSchoolOneName(WxCustomer wxCustomer, SchoolDto schoolDto) {
        School school;
        school = schoolMapper.getSchoolInfoBySchoolName(schoolDto.getSchoolName(), wxCustomer.getCustomerCode());
        if (school != null) {
            return school;
        }
        SysOrg sysOrg = sysOrgService.getSysOrgByOrgCode(wxCustomer.getCustomerCode());
        if (sysOrg == null) {
            return null;
        }
        SysOrg schoolOrg = new SysOrg();
        schoolOrg.setOrgName(schoolDto.getSchoolName());
        schoolOrg.setProvince(schoolDto.getProvince());
        schoolOrg.setOrgType("2");
        schoolOrg.setCity(schoolDto.getCity());
        schoolOrg.setPid(sysOrg.getId());
        ResultVO resultVO = sysOrgService.save(schoolOrg);
        school = new School();
        BeanUtils.copyProperties(schoolDto, school);
        if (RespCode.SUCCESS.getCode() == resultVO.getCode()) {
            SysOrg data = (SysOrg) resultVO.getData();
            school.setId(data.getId());
            school.setOrgCode(data.getOrgCode());
            school.setOrgId(sysOrg.getId());
            school.setPhone(wxCustomer.getPhone());
            school.setCreateTime(new Date().getTime());
            school.setUpdateTime(new Date().getTime());
        } else {
            return null;
        }
        schoolMapper.insert(school);
        return school;
    }

    @Override
    public Grade createGradeOneName(Grade grade) {
        Grade oldGrade = gradeService.getGradeByGradeNameAndSchoolId(grade.getSchoolId(), grade.getGradeName());
        if (oldGrade != null) {
            return oldGrade;
        }
        grade.setCreateTime(new Date().getTime());
        grade.setUpdateTime(new Date().getTime());
        return gradeService.save(grade);
    }

    @Override
    public Classes createClassesOneName(Classes classes) {
        Classes oldClasses = classesService.getClassesByGradeIdAndClassesName(classes.getGradeId(), classes.getClassesName());
        if (oldClasses != null) {
            return oldClasses;
        }
        classes.setCreateTime(new Date().getTime());
        classes.setUpdateTime(new Date().getTime());
        return classesService.save(classes);
    }

    @Override
    public Student createStudentOneStuNo(Integer schoolId, Student student) {
        Student oldStudent = studentMapper.getStudentByStudentNoAndSchoolId(schoolId, student.getStudentNo());
        if (oldStudent != null) {
            return oldStudent;
        }
        studentMapper.insert(student);
        return student;
    }

    @Override
    public BindingStudentDto initDefaultCampusValue(WxCustomer wxCustomer, BindingStudentDto data) {
        SchoolDto schoolDto = data.getSchoolDto();
        if (schoolDto == null) {
            schoolDto = new SchoolDto();
        }
        schoolDto.setSchoolName(StringUtils.isNotBlank(schoolDto.getSchoolName()) ?
                schoolDto.getSchoolName() : wxCustomer.getSchoolName());
        schoolDto.setArea(StringUtils.isNotBlank(schoolDto.getArea()) ? schoolDto.getArea() : wxCustomer.getArea());
        schoolDto.setCity(StringUtils.isNotBlank(schoolDto.getCity()) ? schoolDto.getCity() : wxCustomer.getCity());
        schoolDto.setProvince(StringUtils.isNotBlank(schoolDto.getProvince()) ? schoolDto.getProvince() : wxCustomer.getProvince());
        schoolDto.setEduStage(StringUtils.isNotBlank(schoolDto.getEduStage()) ? schoolDto.getEduStage() : wxCustomer.getEduStage());
        data.setSchoolDto(schoolDto);
        GradeDto gradeDto = new GradeDto();
        gradeDto.setGradeNames(data.getGradeDto() != null && StringUtils.isNotBlank(data.getGradeDto().getGradeNames()) ?
                data.getGradeDto().getGradeNames() : wxCustomer.getGradeNames());
        data.setGradeDto(gradeDto);
        ClassesDto classesDto = new ClassesDto();
        classesDto.setClassesName(data.getClassesDto() != null && StringUtils.isNotBlank(data.getClassesDto().getClassesName()) ? data.getClassesDto().getClassesName() : wxCustomer.getClassesName());
        data.setClassesDto(classesDto);
        return data;
    }

    /**
     * 判断设备是否在线
     *
     * @param imei 设备imei号
     * @return 设备是否在线
     */
    public boolean deviceOnline(String imei) {
        boolean isOnline = redisService.hasKey(Constants.DEVICE_ONLINE_PREFIX + imei);
        return isOnline;
    }

    /**
     * 获取当前时间的时分秒（HHmmss）
     *
     * @return
     */
    public String getCurTime() {
        Date d = new Date();
        SimpleDateFormat sbf = new SimpleDateFormat("HH:mm:ss");
        String format = sbf.format(d);
        String[] split = format.split(":");
        String time = split[0].concat(split[1]).concat(split[2]);
        return time;
    }
}
